{
  "openapi": "3.1.0",
  "info": {
    "title": "API Aberta de Recursos Compartilhados",
    "description": "Gerencie recursos compartilhados (proxies, grupos e tags) por meio da API aberta do MoreLogin.\n\n**URL base**: `https://api.morelogin.com`\n\nA autenticación é feita via token OAuth2 Bearer. Consulte [Autenticação](../Getting%20Started/authentication.md) para obter detalhes.\n",
    "version": "2026-09-05"
  },
  "tags": [
    {
      "name": "Proxy Management",
      "description": "Criar, atualizar, excluir e listar configurações de proxy"
    },
    {
      "name": "Group Management",
      "description": "Criar, atualizar, excluir e listar grupos de ambientes"
    },
    {
      "name": "Tag Management",
      "description": "Criar, atualizar, excluir e listar tags de ambientes"
    },
    {
      "name": "Webhook Management",
      "description": "Configure o endpoint de callback da equipe que recebe os eventos de webhook"
    }
  ],
  "paths": {
    "/proxyInfo/page": {
      "post": {
        "summary": "Obtendo uma lista de proxies",
        "deprecated": false,
        "description": "Lista as configurações de proxy da equipe, página por página.\n- **Efeito**: nenhum. Somente leitura. É seguro repetir com recuo limitado.\n- **Observação**: as senhas são omitidas para membros comuns e para proxies na nuvem e dinâmicos. Os proxies dinâmicos aparecem aqui, mas são gerenciados em outro lugar e não podem ser editados pelos endpoints de proxy.",
        "operationId": "queryProxyInfoPageUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^\\d+$",
                    "description": "ID de proxy opcional para correspondência exata. Envie o ID de 64 bits como string decimal para evitar perda de precisão. Omita para consultar sem filtro por ID. Os demais filtros e a paginação continuam sendo aplicados.",
                    "example": "1800000000000101"
                  },
                  "pageNo": {
                    "type": "integer",
                    "description": "Número da página atual (começa em 1)",
                    "example": 1
                  },
                  "pageSize": {
                    "type": "integer",
                    "description": "Número de itens por página",
                    "example": 10
                  },
                  "isCloudPhoneProxy": {
                    "type": "boolean",
                    "description": "Indica se o proxy é para uso em cloud phone.\n- `true`: Excluir IPs locais ou privados (por exemplo, 127.0.0.1, 360, pia, faixas privadas)\n- `false`: Retornar todos os proxies\n",
                    "example": false
                  },
                  "proxyCategoryType": {
                    "type": "integer",
                    "description": "Categoria do proxy:\n- `1` = Plataforma em nuvem\n- `2` = IP próprio\n",
                    "example": 2
                  },
                  "proxyIp": {
                    "type": "string",
                    "description": "Filtrar por endereço IP do proxy (correspondência parcial)",
                    "example": ""
                  },
                  "proxyName": {
                    "type": "string",
                    "description": "Filtrar por nome do proxy (correspondência parcial)",
                    "example": ""
                  },
                  "proxyProviders": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Lista de IDs de tipos de dispositivo de proxy. Valores aceitos:\n- `0` = Nenhum\n- `4` = Oxylabs\n- `5` = Proxys.io\n- `6` = GeoSurf\n- `7` = Luminati\n- `8` = Lumauto\n- `9` = Oxylabsauto\n- `10` = Trojan\n- `11` = Shadowsocks\n- `12` = vmess\n- `13` = ABCPROXY\n- `14` = LunaProxy\n- `15` = IPHTML\n- `16` = PiaProxy\n- `17` = 922S5\n",
                    "example": []
                  },
                  "proxyStatus": {
                    "type": "integer",
                    "description": "Status de atribuição do proxy:\n- `0` = Normal\n- `1` = Não atribuído\n- `2` = Em atualização\n- `3` = Expirado\n- `4` = Expira em breve  \n> Nota: proxies próprios sempre usam o status `1`.\n",
                    "example": 1
                  },
                  "proxyCheckStatus": {
                    "type": "integer",
                    "description": "Status da verificação do proxy:\n- `0` = Pendente\n- `1` = Sucesso\n- `2` = Falhou\n- `3` = Erro desconhecido\n",
                    "example": 1
                  },
                  "proxyTypes": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Tipos de protocolo do proxy:\n- `0` = HTTP\n- `1` = HTTPS\n- `2` = SOCKS5\n- `3` = SSH\n",
                    "example": []
                  }
                },
                "required": []
              },
              "example": {
                "id": "1800000000000101",
                "pageNo": 1,
                "pageSize": 10,
                "isCloudPhoneProxy": false,
                "proxyCategoryType": 2,
                "proxyIp": "",
                "proxyName": "",
                "proxyProviders": [],
                "proxyStatus": 1,
                "proxyCheckStatus": 1,
                "proxyTypes": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data.dataList` contém os registros da página solicitada e é um array vazio quando não há correspondências; `data.total`, `data.current` e `data.pages` descrevem a paginação.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "current": {
                          "type": "string"
                        },
                        "dataList": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "expiryTime": {
                                "description": "Data de expiração",
                                "type": "string"
                              },
                              "id": {
                                "description": "Chave primária",
                                "type": "string"
                              },
                              "proxyCategoryType": {
                                "description": "Tipo de proxy: 1 - proxy da plataforma; 2 - proxy próprio",
                                "type": "integer"
                              },
                              "proxyCheckStatus": {
                                "description": "Status da detecção: 0 - detecção pendente, 1 - detecção bem-sucedida, 2 - falha na detecção, 3 - erro desconhecido",
                                "type": "integer"
                              },
                              "state": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Estado ou província do proxy. Prioriza a localização detectada do IP de saída e depois a configurada; pode ser null ou uma string vazia.",
                                "example": "California"
                              },
                              "city": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Cidade do proxy. Prioriza a localização detectada do IP de saída e depois a configurada; pode ser null ou uma string vazia.",
                                "example": "Los Angeles"
                              },
                              "proxyPort": {
                                "type": [
                                  "integer",
                                  "null"
                                ],
                                "format": "int32",
                                "description": "Porta de conexão do proxy; não é deduzida do nome. Pode ser null se indisponível.",
                                "example": 1080
                              },
                              "proxyIp": {
                                "description": "IP do proxy",
                                "type": "string"
                              },
                              "exportIp": {
                                "description": "IP de saída",
                                "type": "string"
                              },
                              "countryCode": {
                                "description": "countryCode",
                                "type": "string"
                              },
                              "proxyName": {
                                "description": "Nome do proxy",
                                "type": "string"
                              },
                              "proxyProvider": {
                                "description": "Tipo de proxy: valor padrão 0 - nenhum 4-Oxylabs 5-Proxys.io 7-Luminati 8-Lumauto 9-Oxylabsauto 10-Trojan，11-Shadowsocks 13-ABCPROXY 14-LunaProxy 15-IPHTML 16-PiaProxy 17-922S5\n",
                                "type": "integer"
                              },
                              "proxyType": {
                                "description": "Tipo de proxy: 0 - http, 1 - https, 2 - socks5, 3 - ssh",
                                "type": "integer"
                              },
                              "username": {
                                "description": "Usuário do proxy",
                                "type": "string"
                              },
                              "password": {
                                "description": "Senha do proxy",
                                "type": "string"
                              },
                              "refreshUrl": {
                                "description": "URL de atualização do proxy",
                                "type": "string"
                              }
                            }
                          }
                        },
                        "pages": {
                          "type": "string"
                        },
                        "total": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "current",
                        "dataList",
                        "pages",
                        "total"
                      ]
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": null,
                  "data": {
                    "current": "1",
                    "dataList": [
                      {
                        "expiryTime": "2026-09-01 12:00:00",
                        "id": "1673823102599682",
                        "proxyCategoryType": 1,
                        "proxyCheckStatus": 1,
                        "state": "California",
                        "city": "Los Angeles",
                        "proxyPort": 1080,
                        "proxyIp": "string",
                        "exportIp": "9222",
                        "countryCode": "string",
                        "proxyName": "example-name",
                        "proxyProvider": 1,
                        "proxyType": 1,
                        "username": "example-name",
                        "password": "string",
                        "refreshUrl": "https://example.com/resource"
                      }
                    ],
                    "pages": "1",
                    "total": "1"
                  },
                  "requestId": "0d8b6f1c-9f4e-4d02-9d1a-7c3f5a1b2c3d"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/proxyInfo/add": {
      "post": {
        "summary": "Adicionando proxy",
        "deprecated": false,
        "description": "Cria uma configuração de proxy na equipe.\n- **Pré-requisitos**: `proxyPort` é obrigatório e precisa estar entre 1 e 65535, e `proxyProvider` precisa ser um serviço reconhecido.\n- **Efeito**: insere um registro de proxy e retorna o identificador dele, pronto para vincular a perfis. Nada é enviado ao serviço do proxy.\n- **Conclusão**: sincrônica.\n- **Nova tentativa**: **não há verificação de unicidade de nome nem de configuração.** Enviar o mesmo corpo duas vezes produz dois proxies com dois identificadores. Depois de um timeout, procure em `/proxyInfo/page` antes de reenviar.\n\nErros de negócio documentados: `14023`. Consulte [Error Codes](../Getting%20Started/error-codes.md) para o significado de cada código. Qualquer operação também pode retornar os códigos comuns.",
        "operationId": "addUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "city": {
                    "type": "string",
                    "description": "Cidade",
                    "example": ""
                  },
                  "country": {
                    "type": "string",
                    "description": "Código do país (ISO 3166-1 alfa-2). Obrigatório apenas se proxyProvider=17.\n",
                    "example": "AD"
                  },
                  "encryptionType": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Tipo de criptografia; os valores válidos são números inteiros de 1 a 14.",
                    "example": 14
                  },
                  "ipChangeAction": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Ação na mudança de IP: 0 = Bloquear, 1 = Avisar",
                    "example": 1
                  },
                  "ipMonitor": {
                    "type": "boolean",
                    "description": "Ativar o monitoramento de mudanças de IP",
                    "example": false
                  },
                  "password": {
                    "type": "string",
                    "description": "Senha para autenticação do proxy",
                    "example": ""
                  },
                  "proxyIp": {
                    "type": "string",
                    "description": "Endereço IP do proxy",
                    "example": "8.10.22.46"
                  },
                  "proxyName": {
                    "type": "string",
                    "description": "Nome do proxy (aceita marcadores como {{random}})",
                    "example": "sock5_{{random}}"
                  },
                  "proxyPort": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Número da porta do proxy",
                    "example": 65534
                  },
                  "proxyProvider": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Tipo de tipo de proxy:\n0=HTTP, 1=HTTPS, 2=SOCKS5, 3=SSH, 4=Oxylabs, 5=Proxys.io, 6=GeoSurf, 7=Luminati, 8=Lumauto, 9=Oxylabsauto, 10=Trojan, 11=Shadowsocks, 12=vmess, 13=ABCPROXY, 14=LunaProxy, 15=IPHTML, 16=PiaProxy, 17=922S5.\nRegras especiais:\n- Se proxyProvider for 7 ou 8, proxyType é obrigatório.\n- Se proxyProvider for 17, country é obrigatório; state e city são opcionais.\n",
                    "example": 2
                  },
                  "proxyType": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Tipo de protocolo do proxy: 0=HTTP, 1=HTTPS, 2=SOCKS5, 3=SSH.\nObrigatório apenas quando proxyProvider for 7 ou 8.\n",
                    "example": 1
                  },
                  "refreshUrl": {
                    "type": "string",
                    "description": "URL para atualizar o IP do proxy dinâmico (se suportado)",
                    "example": ""
                  },
                  "state": {
                    "type": "string",
                    "description": "Estado/Província",
                    "example": ""
                  },
                  "username": {
                    "type": "string",
                    "description": "Usuário para autenticação do proxy",
                    "example": ""
                  }
                },
                "required": [
                  "proxyIp",
                  "proxyPort",
                  "proxyProvider"
                ]
              },
              "example": {
                "proxyIp": "8.10.22.46",
                "proxyPort": 65534,
                "proxyProvider": 2,
                "proxyType": 1,
                "country": "AD",
                "state": "",
                "city": "",
                "encryptionType": 14,
                "ipChangeAction": 1,
                "ipMonitor": false,
                "proxyName": "sock5_{{random}}",
                "refreshUrl": "",
                "username": "",
                "password": ""
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um único valor inteiro.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "description": "ID do proxy",
                      "type": "integer"
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": 0,
                  "requestId": "abcd1234"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/proxyInfo/update": {
      "post": {
        "summary": "Modificando informações de proxy",
        "deprecated": false,
        "description": "Atualiza uma configuração de proxy.\n- **Pré-requisitos**: o proxy precisa existir na equipe. **Proxies dinâmicos não podem ser atualizados** por este endpoint. O serviço precisa ser um valor reconhecido.\n- **Efeito**: é uma sobrescrita completa, não um patch: os campos que você omitir voltam aos valores padrão em vez de manter os atuais. Leia o proxy primeiro e envie-o de volta completo.\n- **Propagação**: os perfis mantêm o vínculo porque só o registro do proxy muda, mas um navegador ou Cloud Phone que já esteja em execução continua usando os dados de conexão com que iniciou. Reinicie-o para adotar os novos.\n- **Conclusão**: sincrônica. Sem bloqueio otimista, então atualizações simultâneas são resolvidas pela última escrita.\n\nErros de negócio documentados: `14003`, `14023`. Consulte [Error Codes](../Getting%20Started/error-codes.md) para o significado de cada código. Qualquer operação também pode retornar os códigos comuns.",
        "operationId": "updateProxyUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "proxyIp",
                  "proxyPort",
                  "proxyProvider"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "ID único do proxy"
                  },
                  "proxyIp": {
                    "type": "string",
                    "description": "Endereço IP do servidor proxy"
                  },
                  "proxyPort": {
                    "type": "integer",
                    "description": "Porta do servidor proxy"
                  },
                  "proxyName": {
                    "type": "string",
                    "description": "Nome personalizado do proxy"
                  },
                  "country": {
                    "type": "string",
                    "description": "País (por exemplo, \"US\", \"CN\")"
                  },
                  "city": {
                    "type": "string",
                    "description": "Nome da cidade"
                  },
                  "username": {
                    "type": "string",
                    "description": "Usuário de autenticação (se necessário)"
                  },
                  "password": {
                    "type": "string",
                    "description": "Senha de autenticação (se necessária)"
                  },
                  "proxyType": {
                    "type": "integer",
                    "description": "Tipo de protocolo do proxy:\n- `0` = HTTP\n- `1` = HTTPS\n- `2` = SOCKS5\n- `3` = SSH\n"
                  },
                  "proxyProvider": {
                    "type": "integer",
                    "description": "ID do tipo de proxy:\n- `0` = HTTP\n- `1` = HTTPS\n- `2` = SOCKS5\n- `3` = SSH\n- `4` = Oxylabs\n- `5` = Proxys.io\n- `6` = GeoSurf\n- `7` = Luminati\n- `8` = Lumauto\n- `9` = Oxylabsauto\n- `10` = Trojan\n- `11` = Shadowsocks\n- `12` = vmess\n- `13` = ABCPROXY\n- `14` = LunaProxy\n- `15` = IPHTML\n- `16` = PiaProxy\n- `17` = 922S5\n"
                  },
                  "encryptionType": {
                    "type": "integer",
                    "description": "Tipo de criptografia (específico do serviço; normalmente 0 para sem criptografia)"
                  },
                  "ipMonitor": {
                    "type": "boolean",
                    "description": "Ativar o monitoramento de mudanças de IP"
                  },
                  "ipChangeAction": {
                    "type": "integer",
                    "description": "Ação a executar quando o IP muda:\n- `1` = Notificar / Atualizar (valor comum)\n> Consulte a documentação do sistema para ver todas as opções.\n"
                  },
                  "refreshUrl": {
                    "type": "string",
                    "description": "URL para acionar a atualização do IP (se o serviço suportar)"
                  },
                  "state": {
                    "type": "string",
                    "description": "Campo reservado ou estado personalizado (opcional)"
                  }
                }
              },
              "example": {
                "id": "1566403036579198",
                "proxyIp": "108.11.23.85",
                "proxyPort": 4096,
                "proxyName": "MyProxy",
                "country": "US",
                "city": "New York",
                "username": "",
                "password": "",
                "proxyType": 0,
                "proxyProvider": 0,
                "encryptionType": 0,
                "ipMonitor": true,
                "ipChangeAction": 1,
                "refreshUrl": "",
                "state": ""
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. Esta operação não retorna carga útil; o resultado é informado por `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "requestId": "efgh5678"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/proxyInfo/delete": {
      "post": {
        "summary": "Excluir proxy",
        "deprecated": false,
        "description": "Exclui uma ou mais configurações de proxy.\n- **Pré-requisitos**: pelo menos um identificador precisa ser resolvido dentro da equipe; os que não são resolvidos são ignorados em silêncio. **Um proxy de plataforma na nuvem que não expirou não pode ser excluído** e é informado com um erro específico.\n- **Efeito**: os proxies próprios são removidos e desvinculados de qualquer servidor de salto. Um proxy de plataforma na nuvem já expirado é, em vez disso, marcado para liberação, a assinatura dele é cancelada e o IP é liberado **de forma assíncrona**: a liberação pode ainda estar em andamento quando a resposta chega.\n- **Efeitos em cascata**: os perfis e os Cloud Phones vinculados ao proxy **não são bloqueados nem desvinculados**. Eles continuam apontando para o proxy excluído e as sessões em execução não são interrompidas. Revincule-os com `/env/setProxy/batch` antes de excluir.\n- **Nova tentativa**: os identificadores são processados um a um e a chamada é interrompida na primeira rejeição, então o lote pode ser aplicado parcialmente. Releia `/proxyInfo/page` antes de repetir.\n\nErros de negócio documentados: `14017`, `14024`. Consulte [Error Codes](../Getting%20Started/error-codes.md) para o significado de cada código. Qualquer operação também pode retornar os códigos comuns.",
        "operationId": "deleteProxyUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "integer",
                  "format": "int64"
                }
              },
              "example": [
                1054661322597744600,
                1054661322597744600
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. Esta operação não retorna carga útil; o resultado é informado por `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "requestId": "ijkl9012"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/page": {
      "post": {
        "operationId": "envgroupPagePost",
        "summary": "Obtenha uma lista de grupos",
        "deprecated": false,
        "description": "Lista os grupos de perfis, página por página.\n- **Efeito**: nenhum. Somente leitura. É seguro repetir com recuo limitado.\n- **Observação**: quando a equipe autoriza o acesso por grupo, um membro que não tem nenhuma concessão de grupo recebe uma página vazia em vez de um erro.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "groupName": {
                    "type": "string",
                    "title": "Nome do grupo (correspondência parcial)"
                  },
                  "pageNo": {
                    "type": "integer",
                    "title": "Página atual"
                  },
                  "pageSize": {
                    "type": "integer",
                    "title": "Itens por página"
                  }
                },
                "required": [
                  "groupName",
                  "pageNo",
                  "pageSize"
                ]
              },
              "example": {
                "groupName": "132-kernel",
                "pageNo": 1,
                "pageSize": 10
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data.dataList` contém os registros da página solicitada e é um array vazio quando não há correspondências; `data.total`, `data.current` e `data.pages` descrevem a paginação.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "current": {
                          "type": "string"
                        },
                        "dataList": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "ID do grupo",
                                "type": "string"
                              },
                              "groupName": {
                                "description": "Nome do grupo",
                                "type": "string"
                              }
                            }
                          }
                        },
                        "pages": {
                          "type": "string"
                        },
                        "total": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "current",
                        "dataList",
                        "pages",
                        "total"
                      ]
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": {
                    "current": "0",
                    "dataList": [
                      {
                        "id": "0",
                        "groupName": ""
                      }
                    ],
                    "pages": "0",
                    "total": "0"
                  },
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/edit": {
      "post": {
        "operationId": "envgroupEditPost",
        "summary": "Modificar informações de agrupamento",
        "deprecated": false,
        "description": "Renomeia um grupo de perfis.\n- **Pré-requisitos**: o grupo precisa existir na equipe, quem chama precisa ter autorização para ele, e o nome novo não pode colidir com outro grupo. A verificação de unicidade só é executada quando o nome realmente muda.\n- **Efeito**: renomeia o grupo. Os perfis permanecem nele: eles referenciam o grupo por identificador, então nada mais precisa ser atualizado.\n- **Conclusão**: sincrônica e idempotente.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "groupName",
                  "id"
                ],
                "properties": {
                  "groupName": {
                    "type": "string",
                    "description": "Novo nome do grupo de ambientes"
                  },
                  "id": {
                    "type": "string",
                    "description": "ID único do grupo a ser atualizado"
                  }
                }
              },
              "example": {
                "groupName": "Group-1574544945848579",
                "id": "1574525425557584"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um único valor booleano.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean",
                      "description": "Resultado"
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": null,
                  "data": true,
                  "requestId": "0d8b6f1c-9f4e-4d02-9d1a-7c3f5a1b2c3d"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/create": {
      "post": {
        "operationId": "envgroupCreatePost",
        "summary": "Adicionar grupo",
        "deprecated": false,
        "description": "Cria um grupo de perfis.\n- **Pré-requisitos**: o nome não pode estar vazio, admite no máximo 100 caracteres e não pode já estar em uso por um grupo da equipe. **Uma equipe é limitada a 1000 grupos.**\n- **Efeito**: cria o grupo. Quando a equipe autoriza o acesso por grupo e quem chama não é o proprietário, o acesso ao novo grupo também é concedido a quem chama.\n- **Conclusão**: sincrônica; `data` traz o identificador do novo grupo.\n- **Nova tentativa**: um nome duplicado é rejeitado em vez de reutilizar o grupo existente, então uma repetição depois de uma chamada que teve sucesso mas cuja resposta você não viu falha com um erro de nome duplicado; isso é sinal de que a primeira chamada funcionou. Confirme com `/envgroup/page`.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "security": [
          {
            "Authorization": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um objeto com os campos `id` e `groupName`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "description": "Os dados retornados pela operação",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID do grupo",
                          "type": "string"
                        },
                        "groupName": {
                          "description": "Nome do grupo",
                          "type": "string"
                        }
                      }
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": null,
                  "data": {
                    "id": "1673823102599682",
                    "groupName": "example-name"
                  },
                  "requestId": "0d8b6f1c-9f4e-4d02-9d1a-7c3f5a1b2c3d"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/delete": {
      "post": {
        "operationId": "envgroupDeletePost",
        "summary": "Excluir grupo",
        "deprecated": false,
        "description": "Exclui um ou mais grupos de perfis.\n- **Pré-requisitos**: pelo menos um identificador precisa ser resolvido dentro da equipe e quem chama precisa ter autorização para ele; identificadores que não são resolvidos são ignorados em silêncio.\n- **Efeito**: exclui os grupos e as concessões de acesso de membros a eles. Os perfis de navegador e os Cloud Phones que estavam neles ficam sem grupo, então nenhuma referência órfã de grupo é deixada para trás. Ativar o indicador de excluir ambientes move, além disso, os perfis para os quais você tem autorização **para a lixeira**; eles não são destruídos, e os Cloud Phones nunca são afetados por esse indicador.\n- **Conclusão**: sincrônica, mas **não atômica**. O grupo é excluído primeiro e as etapas seguintes ainda podem falhar, por exemplo quando um perfil está em execução ou em transferência, deixando o grupo excluído e os perfis sem serem movidos.\n- **Nova tentativa**: verifique com `/envgroup/page` e a lista de perfis antes de repetir.\n\nErros de negócio documentados: `19064`. Consulte [Error Codes](../Getting%20Started/error-codes.md) para o significado de cada código. Qualquer operação também pode retornar os códigos comuns.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "ID único do grupo a ser atualizado"
                  },
                  "isDeleteAllEnv": {
                    "type": "boolean",
                    "description": "Excluir os ambientes do grupo? false: não excluir; true: excluir"
                  }
                }
              },
              "example": {
                "ids": [
                  "string"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um único valor booleano.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": true,
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/all": {
      "get": {
        "operationId": "envtagAllGet",
        "summary": "Obtendo uma lista de tags",
        "deprecated": false,
        "description": "Retorna todas as etiquetas de perfil da equipe.\n- **Efeito**: nenhum. Somente leitura. É seguro repetir com recuo limitado.\n- **Observação**: este endpoint **não é paginado e as etiquetas não têm limite no servidor**, então a resposta cresce com o número de etiquetas que a sua equipe criou. Dimensione o seu cliente de acordo.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um array de objetos com os campos `id` e `tagName` e um array vazio quando não há nada a retornar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID das tags",
                            "type": "string"
                          },
                          "tagName": {
                            "description": "Nome das tags",
                            "type": "string"
                          }
                        }
                      }
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": [
                    {
                      "id": "0",
                      "tagName": ""
                    }
                  ],
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/create": {
      "post": {
        "operationId": "envtagCreatePost",
        "summary": "Criar etiquetas",
        "deprecated": false,
        "description": "Cria uma etiqueta de perfil.\n- **Pré-requisitos**: o nome não pode estar vazio, admite no máximo 100 caracteres e não pode já estar em uso por uma etiqueta da equipe.\n- **Efeito**: cria a etiqueta e retorna o identificador dela. Diferente dos grupos, as etiquetas não têm limite de quantidade.\n- **Nova tentativa**: um nome duplicado é rejeitado em vez de reutilizar a etiqueta existente. Confirme com `/envtag/all`.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tagName": {
                    "type": "string",
                    "description": "nome da tag"
                  }
                }
              },
              "example": {
                "tagName": "Tag-123"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um objeto com os campos `id` e `tagName`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID das tags",
                          "type": "string"
                        },
                        "tagName": {
                          "description": "Nome das tags",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "tagName"
                      ]
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    },
                    "error": {
                      "type": "object",
                      "properties": {}
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": {
                    "id": "0",
                    "tagName": ""
                  },
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/edit": {
      "post": {
        "operationId": "envtagEditPost",
        "summary": "Modificar informações das etiquetas",
        "deprecated": false,
        "description": "Renomeia uma etiqueta de perfil.\n- **Pré-requisitos**: a etiqueta precisa existir na equipe e o nome novo não pode colidir com outra etiqueta.\n- **Efeito**: renomeia a etiqueta. Os vínculos existentes não são afetados e os perfis mostram o nome novo imediatamente.\n- **Conclusão**: sincrônica e idempotente.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "ID da tag"
                  },
                  "tagName": {
                    "type": "string",
                    "description": "nome da tag"
                  }
                }
              },
              "example": {
                "id": "1564715845550177",
                "tagName": "Updated-123"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um único valor booleano.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    },
                    "error": {
                      "type": "object",
                      "properties": {}
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": true,
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/delete": {
      "post": {
        "operationId": "envtagDeletePost",
        "summary": "Excluir etiquetas",
        "deprecated": false,
        "description": "Exclui uma ou mais etiquetas de perfil.\n- **Pré-requisitos**: pelo menos um identificador precisa ser resolvido dentro da equipe; os que não são resolvidos são ignorados em silêncio.\n- **Efeito**: exclui as etiquetas. A etiqueta desaparece de todos os perfis que a carregavam, e nenhum perfil é excluído. Este endpoint gerencia apenas etiquetas de perfil: as etiquetas de arquivo do Cloud Storage são gerenciadas separadamente.\n- **Conclusão**: sincrônica. Uma chamada repetida informa que as etiquetas são inválidas, o que significa que a primeira teve sucesso.\n\nErros de negócio documentados: `19105`. Consulte [Error Codes](../Getting%20Started/error-codes.md) para o significado de cada código. Qualquer operação também pode retornar os códigos comuns.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "ID único da tag a ser atualizada"
                  }
                }
              },
              "example": {
                "ids": [
                  "string"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um único valor booleano.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": true,
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/webhook/config": {
      "post": {
        "operationId": "webhookConfigPost",
        "summary": "Configurar o webhook da equipe",
        "deprecated": false,
        "description": "Cria ou substitui a configuração de webhook da equipe.\n\n- **Pré-requisitos**: `callbackUrl` deve ser uma URL HTTPS de 1 a 1024 caracteres, com host, sem informações de usuário, sem fragmento e com porta válida. Todos os endereços para os quais ela resolver precisam ser roteáveis publicamente; faixas de localhost, privadas, link-local, CGNAT, metadados de nuvem, reservadas por protocolo, de documentação e 6to4 são rejeitadas. A mesma verificação ocorre de novo quando uma entrega abre a conexão, então um nome que depois resolva para uma faixa privada faz aquela entrega falhar em vez de alcançar sua rede.\n- **Efeito**: faz upsert da única configuração da equipe do contexto do servidor. `teamId` nunca é lido da requisição, então quem chama não pode configurar outra equipe. Os endpoints da Local API e da Open API leem e gravam o mesmo registro, e a resposta reflete o que foi armazenado.\n- **Desativação**: `enabled: false` mantém a URL e interrompe a criação de novos eventos. Eventos já na fila são cancelados um a um se a configuração ainda estiver desativada quando forem autorizados, então reativar logo permite que continuem.\n- **Repetição**: seguro. O salvamento é um upsert por equipe, então repetir a mesma requisição converge para o mesmo estado.\n\nConsulte [Webhooks](../Getting%20Started/webhooks.md) para o contrato de callback, os nomes de evento e a programação de novas tentativas.\n\nErros de negócio documentados: `41001`. Consulte [Error Codes](../Getting%20Started/error-codes.md) para o significado de cada código. Qualquer operação também pode retornar os códigos comuns.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "callbackUrl": {
                    "description": "URL HTTPS que recebe os eventos. De 1 a 1024 caracteres.",
                    "type": "string",
                    "maxLength": 1024
                  },
                  "enabled": {
                    "description": "Indica se a entrega está ativada para a equipe.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "callbackUrl",
                  "enabled"
                ]
              },
              "example": {
                "callbackUrl": "https://example.com/morelogin/webhook",
                "enabled": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso. `data` é um objeto com os campos `callbackUrl` e `enabled`, refletindo a configuração armazenada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Código de resultado. `0` indica sucesso; outros códigos indicam exceções.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Mensagem de erro",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "callbackUrl": {
                          "description": "A URL HTTPS de callback armazenada.",
                          "type": "string"
                        },
                        "enabled": {
                          "description": "Indica se a entrega está ativada para a equipe.",
                          "type": "boolean"
                        }
                      }
                    },
                    "requestId": {
                      "description": "ID da solicitação da operação",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": {
                    "callbackUrl": "https://example.com/morelogin/webhook",
                    "enabled": true
                  },
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    }
  },
  "webhooks": {
    "cloud_phone.power_on": {
      "post": {
        "operationId": "webhookCloudPhonePowerOn",
        "summary": "Ligamento do cloud phone concluído",
        "description": "Enviado quando um ligamento chega ao seu resultado final.\n\n`success` é `true` apenas quando o callback do serviço teve êxito e a sincronização local foi confirmada. Uma falha de cobrança, ou uma verificação de proxy assíncrona que falha e conclui sua limpeza, informa um ligamento com falha e não emite um desligamento separado. Trabalhos adiados, como instalar aplicativos predefinidos, não alteram o resultado.\n\nSe um desligamento interromper a inicialização, aquela tentativa não produz evento de ligamento; o desligamento bem-sucedido posterior ainda produz seu próprio `cloud_phone.power_off`.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "c7f3a2b10d8e4f6a9c1b2d3e4f5a6b7c",
                "eventType": "cloud_phone.power_on",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": false,
                  "code": "33318",
                  "message": "Operation failed"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.power_off": {
      "post": {
        "operationId": "webhookCloudPhonePowerOff",
        "summary": "Cloud phone desligado",
        "description": "Enviado quando um desligamento teve êxito. Um desligamento com falha não produz este evento, então aqui `result.success` é sempre `true`.\n\n`data.reason` registra por que o aparelho parou.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhonePowerOffWebhookEvent"
              },
              "example": {
                "eventId": "5b1d0c9e7a2f4d38b6c5a4e3f2d1c0b9",
                "eventType": "cloud_phone.power_off",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001",
                  "reason": "MONEY_SAVING"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.restart": {
      "post": {
        "operationId": "webhookCloudPhoneRestart",
        "summary": "Reinício do cloud phone concluído",
        "description": "Enviado quando um reinício chega ao seu resultado final. `success` é `true` apenas quando o callback do serviço teve êxito e a sincronização local foi confirmada.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "9e4c1a7b3f2d40518a6b5c4d3e2f1a0b",
                "eventType": "cloud_phone.restart",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.reset": {
      "post": {
        "operationId": "webhookCloudPhoneReset",
        "summary": "Redefinição do cloud phone concluída",
        "description": "Enviado quando uma redefinição chega ao seu resultado final. `success` é `true` apenas quando o callback do serviço teve êxito e a sincronização local foi confirmada.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "2f8a6d4c0b9e47138c7d6e5f4a3b2c1d",
                "eventType": "cloud_phone.reset",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.new_machine": {
      "post": {
        "operationId": "webhookCloudPhoneNewMachine",
        "summary": "Novo aparelho com um clique do cloud phone concluído",
        "description": "Enviado quando uma operação de novo aparelho com um clique chega ao seu resultado final. `success` é `true` apenas quando o callback do serviço teve êxito e a sincronização local foi confirmada.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "7c3b1e9d5a4f42068b1c2d3e4f5a6b70",
                "eventType": "cloud_phone.new_machine",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_browser.start": {
      "post": {
        "operationId": "webhookCloudBrowserStart",
        "summary": "Início do cloud browser concluído",
        "description": "Enviado quando o início de um cloud browser chega ao seu resultado final.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudBrowserWebhookEvent"
              },
              "example": {
                "eventId": "4a9f2c7e1b8d43509c6a5b4c3d2e1f00",
                "eventType": "cloud_browser.start",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudBrowserId": "30001",
                  "runId": "40001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_browser.stop": {
      "post": {
        "operationId": "webhookCloudBrowserStop",
        "summary": "Encerramento do cloud browser concluído",
        "description": "Enviado a cada tentativa de encerramento de um cloud browser, com ou sem êxito. Chegar ao estado de encerramento com falha já é um resultado com falha para aquela tentativa; uma nova tentativa manual posterior ou uma liberação forçada contam como uma nova operação e produzem um novo `eventId`.\n\nOs eventos são deduplicados por operação de encerramento, então uma tentativa nunca gera dois eventos e duas tentativas nunca são mescladas. Uma falha interna de arquivamento altera apenas `result`; nunca sobrescreve o `reason` capturado quando o encerramento começou.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudBrowserStopWebhookEvent"
              },
              "example": {
                "eventId": "c7f3a2b10d8e4f6a9c1b2d3e4f5a6b7c",
                "eventType": "cloud_browser.stop",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudBrowserId": "30001",
                  "runId": "40001",
                  "reason": "BROWSER_EXITED"
                },
                "result": {
                  "success": false,
                  "code": "40006",
                  "message": "Operation failed"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "Authorization": {
        "type": "http",
        "description": "Valor do campo access_token da resposta da interface de obtenção do token de acesso",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "parameters": {
      "WebhookEventId": {
        "name": "X-Webhook-Event-Id",
        "in": "header",
        "required": true,
        "description": "O mesmo valor de `eventId` no corpo. Use-o para tornar seu handler idempotente.",
        "schema": {
          "type": "string"
        }
      },
      "WebhookEventType": {
        "name": "X-Webhook-Event-Type",
        "in": "header",
        "required": true,
        "description": "O mesmo valor de `eventType` no corpo, para você rotear sem fazer parsing.",
        "schema": {
          "type": "string"
        }
      },
      "WebhookUserAgent": {
        "name": "User-Agent",
        "in": "header",
        "required": true,
        "description": "Sempre `MoreLogin-Webhook/1.0`.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "WebhookAck": {
        "description": "Qualquer 2xx é considerado entregue. O corpo da resposta é ignorado, então responda o quanto antes e faça o trabalho de forma assíncrona. Qualquer outra coisa, incluindo tempo limite de conexão ou de leitura, conta como falha e é repetida."
      }
    },
    "schemas": {
      "WebhookResult": {
        "type": "object",
        "description": "O resultado final da operação que o evento descreve.",
        "properties": {
          "success": {
            "description": "Indica se a operação teve êxito no final.",
            "type": "boolean"
          },
          "code": {
            "description": "`0` em caso de êxito. Em caso de falha, um código de erro de negócio estável que não depende do idioma.",
            "type": "string"
          },
          "message": {
            "description": "`null` em caso de êxito. Em caso de falha, uma explicação no idioma da equipe, recorrendo a `en-US` quando esse idioma ou seu texto não está disponível.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "success",
          "code",
          "message"
        ]
      },
      "CloudPhoneWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "ID de evento único. As novas tentativas de entrega e as reexecuções internas do mesmo evento o reutilizam, então trate-o como a chave de idempotência.",
            "type": "string"
          },
          "eventType": {
            "description": "Nome de evento estável.",
            "type": "string"
          },
          "eventTime": {
            "description": "Quando o resultado final de negócio ocorreu, em milissegundos de época Unix. Enviado como string.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "A equipe proprietária do recurso.",
                "type": "string"
              },
              "cloudPhoneId": {
                "description": "O cloud phone a que o evento se refere.",
                "type": "string"
              }
            },
            "required": [
              "teamId",
              "cloudPhoneId"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      },
      "CloudPhonePowerOffWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "ID de evento único. As novas tentativas de entrega e as reexecuções internas do mesmo evento o reutilizam, então trate-o como a chave de idempotência.",
            "type": "string"
          },
          "eventType": {
            "description": "Nome de evento estável.",
            "type": "string"
          },
          "eventTime": {
            "description": "Quando o resultado final de negócio ocorreu, em milissegundos de época Unix. Enviado como string.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "A equipe proprietária do recurso.",
                "type": "string"
              },
              "cloudPhoneId": {
                "description": "O cloud phone a que o evento se refere.",
                "type": "string"
              },
              "reason": {
                "description": "Por que o aparelho parou.",
                "type": "string",
                "enum": [
                  "NORMAL",
                  "MONEY_SAVING",
                  "OTHER"
                ]
              }
            },
            "required": [
              "teamId",
              "cloudPhoneId",
              "reason"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      },
      "CloudBrowserWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "ID de evento único. As novas tentativas de entrega e as reexecuções internas do mesmo evento o reutilizam, então trate-o como a chave de idempotência.",
            "type": "string"
          },
          "eventType": {
            "description": "Nome de evento estável.",
            "type": "string"
          },
          "eventTime": {
            "description": "Quando o resultado final de negócio ocorreu, em milissegundos de época Unix. Enviado como string.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "A equipe proprietária do recurso.",
                "type": "string"
              },
              "cloudBrowserId": {
                "description": "O perfil de cloud browser a que o evento se refere.",
                "type": "string"
              },
              "runId": {
                "description": "A instância de execução a que o evento se refere.",
                "type": "string"
              }
            },
            "required": [
              "teamId",
              "cloudBrowserId",
              "runId"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      },
      "CloudBrowserStopWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "ID de evento único. As novas tentativas de entrega e as reexecuções internas do mesmo evento o reutilizam, então trate-o como a chave de idempotência.",
            "type": "string"
          },
          "eventType": {
            "description": "Nome de evento estável.",
            "type": "string"
          },
          "eventTime": {
            "description": "Quando o resultado final de negócio ocorreu, em milissegundos de época Unix. Enviado como string.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "A equipe proprietária do recurso.",
                "type": "string"
              },
              "cloudBrowserId": {
                "description": "O perfil de cloud browser a que o evento se refere.",
                "type": "string"
              },
              "runId": {
                "description": "A instância de execução a que o evento se refere.",
                "type": "string"
              },
              "reason": {
                "description": "Por que a execução parou.",
                "type": "string",
                "enum": [
                  "NORMAL",
                  "MONEY_SAVING",
                  "ENERGY_SAVING",
                  "BROWSER_EXITED",
                  "OTHER"
                ]
              }
            },
            "required": [
              "teamId",
              "cloudBrowserId",
              "runId",
              "reason"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      }
    }
  },
  "servers": [
    {
      "url": "https://api.morelogin.com",
      "description": "Endpoint da MoreLogin Open API"
    }
  ],
  "security": [
    {
      "Authorization": []
    }
  ]
}